﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace PsiIndexer {
  public class PsiConversation {
    private readonly List<PsiChatInfo> _chats;

    private PsiConversation() {
      this._chats = new List<PsiChatInfo>();
    }

    public string Author { get; set; }

    public string OriginFile { get; set; }

    public IEnumerable<PsiChatInfo> Chats {
      get { return this._chats; }
    }

    public static PsiConversation Create(string file) {
      string[] allLines = getAllLines(file);
      if (allLines == null) {
        return null;
      }
      // get author name from file name
      string author = new FileInfo(file).Name.Replace("_at_", "@").Replace(".history", "").Replace("%5f", "_").Replace("%2d", "-");

      var pc = new PsiConversation();
      pc.OriginFile = file;
      pc.Author = author;
      foreach (string line in allLines) {
        PsiChatInfo psi = PsiChatInfo.Create(line);
        if (psi != null) {
          pc.AddChat(psi);
        }
      }
      return pc;
    }

    private void AddChat(PsiChatInfo psi) {
      PsiChatInfo prev = this._chats.LastOrDefault();
      psi.Conversation = this;
      psi.PrevChat = prev;
      if (prev != null) {
        prev.NextChat = psi;
      }
      this._chats.Add(psi);
    }

    private static string[] getAllLines(string file) {
      if (string.IsNullOrEmpty(file)) {
        return null;
      }
      if (!File.Exists(file)) {
        return null;
      }

      string[] allLines;
      try {
        allLines = File.ReadAllLines(file);
        if (!allLines.Any()) {
          return null;
        }
      }
      catch (Exception) {
        return null;
      }
      return allLines;
    }

    public void Update() {
      // search backwards through new history
      string[] allLines = getAllLines(this.OriginFile);
      if (allLines != null) {
        var toAdd = new List<PsiChatInfo>();
        var sameElements = new string[5];
        PsiChatInfo lastPCI = this.Chats.Last();
        int i = 0;
        foreach (string line in allLines.Reverse()) {
          PsiChatInfo testMe = PsiChatInfo.Create(line);
          testMe.Conversation = this;
          if (testMe.Equals(lastPCI)) {
            sameElements = allLines.Reverse().Skip(i).Take(sameElements.Length).ToArray();
            break;
          }
          else {
            // no equality, assume its a new element
            toAdd.Add(testMe);
          }
          i++;
        }
        // test some more elements at the end
        bool foundEnd = true;
        foreach (string element in sameElements) {
          string testMe = allLines.Reverse().ElementAtOrDefault(i++);
          foundEnd &= testMe == element;
          if (!foundEnd) {
            break;
          }
        }
        if (foundEnd) {}
        // add new elements
        foreach (PsiChatInfo pci in Enumerable.Reverse(toAdd)) {
          this.AddChat(pci);
        }
      }
    }

    public override string ToString() {
      return string.Format("{1}:{2}#     => {0}", this.OriginFile, this.Author, this.Chats.Count());
    }
  }
}
